
<template>
  <div class="page-customsetting">
    <Form class="custom-form" label-position="top">
      <FormItem label="运行环境">
        <Select :value="image" @on-change="customChange($event,'image')">
          <Option v-for="item in imageList" :value="item.id" :key="item.id">{{ item.name }}</Option>
        </Select>
      </FormItem>

      <FormItem label="执行文件" class="input-file">
        <AutoComplete
          :key="new Date().getTime()"
          :value="bin"
          @autoBlur="customChange($event,'bin')"
        />
        <i class="iconfont icon-file" @click="binfileVisible = true" />

        <!-- 代码编辑 -->
        <CodeSetting :code="bin" />
      </FormItem>

      <FormItem label="运行参数" class="run-param">
        <Button class="run-setting" type="primary" size="small" @click="argSetting">设置</Button>
      </FormItem>

      <!-- 参数设置 -->
      <FormItem
        :label="`${item.desc}(${item.name})`"
        v-for="(item,index) of args"
        :key="index"
        :class="{'run-param-item':true, 'arg-form-item':true,'bool-form-item': item.formEditType === 'bool' }"
      >
        <!-- 输入框string -->
        <Input
          v-if="item.formEditType === 'string' || !item.formEditType"
          :value="item.value"
          placeholder="请输入参数"
          clearable
          style="width:90%"
          @on-blur="customChange($event,'singleArg',index )"
        />

        <!-- 数字框int -->
        <InputNumber
          v-if="item.formEditType === 'int'"
          :value="item.value"
          placeholder="请输入参数"
          clearable
          style="width:90%"
          :precision="0"
          @on-change="customChange($event,'singleArg',index)"
        />

        <!-- 文件选择 -->
        <template v-if="item.formEditType === 'file'">
          <AutoComplete
            style="width:85%"
            :key="new Date().getTime()"
            :value="item.value"
            @autoBlur="customChange($event,'singleArg',index)"
          />

          <i
            class="iconfont icon-file"
            @click="argFileHandler(item.value,index)"
            style="position: relative;left: 5px;"
          />
        </template>

        <!-- 布尔值 -->
        <Checkbox
          v-model="item.value"
          v-if="item.formEditType === 'bool'"
          @on-change="customChange($event,'singleArg',index)"
        >{{item.desc}}({{item.name}})</Checkbox>

        <i class="iconfont icon-trash" @click="argDel(item.name)"></i>
      </FormItem>

      <FormItem label="运行入口" class="arg-form-item">
        <div v-for="(item,index) of commands" :key="index" style="margin-bottom:5px;">
          <Input
            type="textarea"
            :value="item.name"
            placeholder="请输入运行指令"
            clearable
            style="width:90%;"
            :autosize="true"
            @on-blur="customChange($event,'singleCommand',index);commandsIndex=null"
            v-if="commandsIndex === index"
            v-focus
          />

          <div
            v-else
            class="commands-text"
            @click="commandsIndex=index"
            v-html="getCommandsText(item.name)"
          ></div>

          <i class="iconfont icon-trash" @click="entryDel(index)"></i>
        </div>
      </FormItem>

      <div class="arg-add-icon">
        <Icon type="ios-add-circle-outline" @click="addEntry" />
      </div>
    </Form>
    <div style="text-align: center;">
      <Button
        type="primary"
        @click="setReuseCom"
      >设置为可复用的组件</Button>
      <!-- v-show="!isReused && settingType===wfCode.CUSTOM" -->
    </div>

    <!-- 设置项目参数 -->
    <Modal footer-hide title="设置项目参数" v-model="argVisible" width="700px">
      <arg-setting
        v-if="argVisible"
        :args="args"
        @cancelHandler="argVisible=false"
        @okHandler="argChange"
      />
    </Modal>

    <!-- 设置可复用组件 -->
    <Modal footer-hide title="保存为可复用组件" v-model="reuseFileVisible" width="500px">
      <div>保存该组件进入组件区重复使用，组件的环境，运行文件，参数项目会保存</div>

      <div class="reuse-input">
        <label for>组件名称：</label>
        <Input
          v-model.trim="reuseName"
          placeholder="请输入组件名称"
          :maxlength="20"
          style="width: 280px;"
        />
      </div>

      <div class="reuse-footer">
        <Button @click="reuseFileVisible = false" style="margin-right:8px;">取消</Button>
        <Button type="primary" @click="reuseFile">确定</Button>
      </div>
    </Modal>

    <!-- 参数文件 -->
    <Modal footer-hide title="选择文件" v-model="argfileVisible" width="700px">
      <filedata
        :filePath="argfileValue"
        v-if="argfileVisible"
        @cancelHandler="argfileVisible=false"
        @okHandler="argfileOkHandler"
      />
    </Modal>

    <!-- 选择执行文件 -->
    <Modal footer-hide title="选择执行文件" v-model="binfileVisible" width="700px">
      <filedata
        :filePath="bin"
        v-if="binfileVisible"
        @cancelHandler="binfileVisible=false"
        @okHandler="binfileOkHandler"
      />
    </Modal>
  </div>
</template>

<script>
import { wfCode } from 'assets/scripts/code';
import { mapState, mapMutations } from 'vuex';
import {
  updateCustomNode,
  getImageTypes,
  setReuseNode
} from 'http/api/workflow';

import ArgSetting from '../Common/ArgSetting';
import Filedata from '../Common/Filedata';
import AutoComplete from '../Common/AutoComplete';
import CodeSetting from '../Common/CodeSetting';

import Bus from 'assets/scripts/bus';

export default {
  props: ['nodeInfo'],
  components: {
    ArgSetting,
    Filedata,
    AutoComplete,
    CodeSetting
  },
  data () {
    return {
      wfCode: wfCode,
      name: '',
      pipelineId: '',
      // 任务镜像
      image: '',

      // 执行文件
      bin: '',

      // 运行参数
      argVisible: false,
      args: [],

      // 参数
      argValues: {},

      // 运行入口
      commands: [
        {
          name: ''
        }
      ],
      commandsIndex: null,

      // 设置可复用组件
      reuseFileVisible: false,
      reuseName: '',

      binfileVisible: false,
      outfileVisible: false,

      // 参数文件的选择
      argfileValue: '',
      argfileIndex: null,
      argfileVisible: false,
      isReused: false,
      // 命令提示
      commandsTips: {
        $autoparams:
          '自动参数，python会自动替换为"--key value"的形式，java替换为"-key value"',
        $bin: ''
      }
    };
  },

  watch: {
    nodeInfo () {
      this.setNodeInfo();
    },
    commands () {
      if (this.commands.length === 0) {
        this.commands.push({
          name: ''
        });
      }
    }
  },

  directives: {
    focus: {
      inserted (el) {
        el.firstChild.focus();
      }
    }
  },

  computed: {
    ...mapState({
      currentNode: state => state.workflow.currentNode,
      link: state => state.workflow.link,
      node: state => state.workflow.node,
      imageList: state => state.workflow.imageList,
      settingType: state => state.workflow.settingType
    })
  },

  methods: {
    ...mapMutations(['setNode', 'setImageList']),

    // 设置成可复用组件
    setReuseCom () {
      if (!this.image) {
        this.$Message.error('请选择运行环境');
        return;
      }

      if (!this.bin) {
        this.$Message.error('请选择执行文件');
        return;
      }
      this.reuseFileVisible = true;
    },

    // 参数文件选择
    argFileHandler (value, index) {
      this.argfileValue = value;
      this.argfileIndex = index;
      this.argfileVisible = true;
    },

    // 参数文件选择后
    argfileOkHandler (url) {
      this.customChange(url, 'singleArg', this.argfileIndex);
      this.argfileVisible = false;
    },

    // 设置
    argSetting () {
      this.argVisible = true;
    },

    // 重置编辑信息
    setNodeInfo () {
      let {
        taskType,
        bin,
        commands,
        args,
        name,
        isReused,
        argValues
      } = this.nodeInfo;
      this.name = name;
      this.image = taskType ? taskType.id : '';
      this.bin = bin;
      this.isReused = isReused;

      let commands2 = [];
      if (commands && commands.length > 0) {
        commands.forEach(item => {
          commands2.push({
            name: item
          });
        });
      }

      this.commands = commands2;

      // 参数设置
      if (typeof argValues === 'string') {
        try {
          this.argValues = JSON.parse(argValues);
        } catch (err) {}
      }
      this.args = args;
      if (this.args) {
        this.args.forEach(item => {
          let argValueItem = this.argValues[item.name];
          item.value = argValueItem || item.defaultValue;

          if (item.formEditType === 'int') {
            item.value = Number(item.value);
          }

          if (item.formEditType === 'bool') {
            if (item.value === 'false') {
              item.value = false;
            }
            if (item.value === 'true') {
              item.value = true;
            }
          }

          if (!this.argValues[item.name]) {
            this.argValues[item.name] = item.value;
          }
        });
      }

      // 默认进来后的commandsTips设置
      this.commandsTips['$bin'] = this.bin ? `可执行文件，${this.bin}` : '';
      for (let i in this.argValues) {
        this.commandsTips['$' + i] = `配置的运行参数，值是${this.argValues[i]}`;
      }
    },

    // 数据预览按钮
    dataView () {
      this.showAllData = !this.showAllData;
    },

    // 获取镜像的数据
    getImageData () {
      getImageTypes().then(res => {
        if (res && res.data) {
          this.setImageList(res.data);
        }
      });
    },

    // 参数更改
    argChange (args) {
      this.args = JSON.parse(JSON.stringify(args));
      this.args.forEach(item => {
        let argValueItem = this.argValues[item.name];
        item.value = argValueItem || item.defaultValue;

        if (item.formEditType === 'int') {
          item.value = Number(item.value);
        }

        if (!this.argValues[item.name]) {
          this.argValues[item.name] = item.value;
        }
      });
      this.argVisible = false;
      this.customChange(args, 'args');
    },

    // 添加运行入口
    addEntry () {
      this.commands.push({ name: '' });
    },

    // 入口删除
    entryDel (index) {
      this.commands.splice(index, 1);
      this.updateNodeInfo();
    },

    // 参数删除
    argDel (key) {
      delete this.argValues[key];
      this.args = this.args.filter(item => {
        return item.name !== key;
      });

      this.updateNodeInfo();
    },

    // 重命名组件
    reuseFile () {
      if (!this.reuseName) {
        this.$Message.error('请输入组件名称');
        return;
      }
      setReuseNode({
        pipelineTaskId: this.currentNode.id,
        name: this.reuseName
      }).then(res => {
        if (res) {
          Bus.$emit('updateWorkFlowTree');
          this.reuseFileVisible = false;
          this.isReused = false;
        }
      });
    },

    // 自定义数据修改
    customChange (e, name, index) {
      let nodeName = e.target && e.target.nodeName;
      let value;
      if (nodeName === 'INPUT' || nodeName === 'TEXTAREA') {
        value = e.target.value;
        value = value.trim();
        if (value === '') {
          return;
        }
      } else {
        value = e;
      }

      // 改变单个参数的值
      if (name === 'singleArg') {
        let arg = this.args[index];
        let argName = arg.name;
        this.argValues[argName] = value;
        this.args[index].value = value;
      } else if (name === 'singleCommand') {
        this.commands[index] = { name: value };
      } else if (name === 'args') {
        // 如果没有则新增，有不管
        let obj = {};
        this.args.forEach(item => {
          obj[item.name] = this.argValues[item.name]
            ? this.argValues[item.name]
            : item.defaultValue;
        });
        this.argValues = obj;
      } else {
        this[name] = value;
        if (name === 'image') {
          let len = this.commands.length;
          let command = this.commands[len - 1].name;
          let defaultCommand;
          this.imageList.find(item => {
            if (item.id === this.image) {
              defaultCommand = item.command;
              return true;
            }
          });
          // 没有值的时候自动赋值
          let updateValue = false;
          if (!command) {
            updateValue = true;
          } else {
            // "java -jar $bin $autoparams"
            // python $bin $autoparams
            // python3 $bin $autoparams
            // spark-submit --class mainClass  --master yarn-cluster...
            if (
              (value === '1' && command.indexOf('java') !== 0) ||
              (value === '2' && command.indexOf('python') !== 0) ||
              (value === '3' && command.indexOf('python3') !== 0) ||
              (value === '4' && command.indexOf('spark-submit') !== 0)
            ) {
              updateValue = true;
            }
          }

          if (updateValue) {
            this.commands[len - 1].name = defaultCommand;
          }
        }
      }
      this.updateNodeInfo();
    },

    /**
     * 自定义节点更新
     *
     */
    updateNodeInfo () {
      let { x, y, id } = this.currentNode;
      let commands = [];

      this.commands.forEach(item => {
        commands.push(item.name);
      });

      let param = {
        id: id,
        location: { x, y },
        pipeline: {
          id: this.pipelineId
        },
        taskType: {
          id: this.image
        },
        bin: this.bin,
        args: this.args,
        argValues: JSON.stringify(this.argValues),
        commands
      };

      let wires = [];
      this.link.forEach(item => {
        let { start, end, srcIndex, desIndex } = item;
        if (start === id) {
          wires.push({
            srcId: start,
            desId: end,
            desIndex: desIndex || 0,
            srcIndex: srcIndex || 0
          });
        }
      });

      param.wires = wires;
      param.pipelineTaskNodeType = this.settingType;

      // update后的commandsTips设置
      this.commandsTips['$bin'] = this.bin ? `可执行文件，${this.bin}` : '';
      for (let i in this.argValues) {
        this.commandsTips['$' + i] = `配置的运行参数，值是${this.argValues[i]}`;
      }

      // 先改数据
      this.node[id] = Object.assign({}, this.node[id], param);
      this.setNode(this.node);

      updateCustomNode(param).then(res => {
        this.node[id] = Object.assign({}, this.node[id], res.data);
        this.setNode(this.node);
      });
    },

    // 执行文件
    binfileOkHandler (url) {
      this.bin = url;
      this.customChange(url, 'bin');

      this.binfileVisible = false;
    },

    // 过滤commands然后进行判断
    getCommandsText (text) {
      if (!text && !text.trim()) {
        return text;
      }
      for (let i in this.commandsTips) {
        let index1 = text.indexOf(i);
        let beforeText;
        let afterText;
        let paramlen = i.length;
        if (index1 > -1) {
          beforeText = text.substring(0, index1);
          afterText = text.substring(index1 + paramlen);

          let className;
          if (i === '$autoparams') {
            className = 'command-autoparams';
          } else if (i === '$bin') {
            className = 'command-bin';
          } else {
            className = 'command-common';
          }
          text = `${beforeText}<span class='${className}' title='${this.commandsTips[i]}'>${i}</span>${afterText}`;
        }
      }

      return text;
    }
  },

  mounted () {
    if (this.imageList.length === 0) {
      this.getImageData();
    }
    this.pipelineId = this.$route.query.pipelineId;

    // 节点编辑信息
    if (this.nodeInfo) {
      this.setNodeInfo();
    }
  }
};
</script>

<style rel="stylesheet/less" lang="less" scoped>
@import "../../../assets/theme/themeBlue.less";
.page-customsetting {
  padding: 2px 0;

  .custom-form {
    padding-top: 20px;
    padding-left: 20px;
    padding-right: 20px;
    min-height: 400px;
  }
  .view-btns {
    float: right;
    padding-right: 10px;
  }

  .arg-form-item {
    position: relative;
    .icon-trash {
      cursor: pointer;
      position: absolute;
      right: 0;
    }
  }

  .run-param-item {
    margin-left: 20px;
  }

  .arg-add-icon {
    text-align: center;
    margin-bottom: 10px;
    position: relative;
    top: -10px;
    cursor: pointer;
    .ivu-icon-ios-add-circle-outline {
      font-size: 26px;
    }
  }

  .icon-file {
    color: #888888;
    font-size: 16px;
    cursor: pointer;
  }

  .commands-text {
    display: inline-block;
    border: 1px solid #d6d6d6;
    width: 90%;
    min-height: 32px;
    line-height: 1.5;
    border-radius: 4px;
    font-size: 12px;
    padding: 2px 7px;
    box-sizing: border-box;
    word-break: break-all;
    color: #333333;
    overflow-y: auto;
    cursor: pointer;
    &:hover {
      border-color: @primary;
    }
  }
}
</style>

<style lang="less">
.reuse-footer {
  text-align: right;
  margin-top: 10px;
}
.reuse-input {
  margin-top: 10px;
  .ivu-input-wrapper {
    width: 80%;
  }
}

.bool-form-item .ivu-form-item-label {
  display: none !important;
}
.command-autoparams,
.command-bin,
.command-common {
  padding: 0 1px;
  cursor: pointer;
}
.command-autoparams {
  color: #fad000;
}
.command-bin {
  color: #0cc7c9;
}
.command-common {
  color: #3b98f2;
}

.run-param {
  position: relative;
  .ivu-form-item-content {
    position: absolute;
    left: 60px;
    top: -10px;
  }
}
</style>
